﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;

namespace FusionTileEditor
{
    public partial class Form1 : Form
    {
        public bool Looping = true;

        struct Tile
        {
            private bool m_bCollidable;

            private string m_strTrigger;

            private Rectangle m_SourceRect;

            public bool BCollidable
            {
                get { return m_bCollidable; }
                set { m_bCollidable = value; }
            }

            public string StrTrigger
            {
                get { return m_strTrigger; }
                set { m_strTrigger = value; }
            }

            public Rectangle SourceRect
            {
                get { return m_SourceRect; }
                set { m_SourceRect = value; }
            }

            public Tile(bool bCollidable, string strTrigger, Rectangle SourceRect)
            {
                this.m_bCollidable = bCollidable;
                this.m_SourceRect = SourceRect;
                this.m_strTrigger = strTrigger;
            }
        };

        bool m_bImageLayer = true;
        bool m_bMouseIsDown = false;
        int m_nTileWidth = 64;
        int m_nTileHeight = 64;
        int m_nTileSetWidth = 4;
        int m_nTileSetHeight = 2;
        int m_nMapWidth = 25;
        int m_nMapHeight = 20;
        int m_nImgID = -1;

        string m_strImageName;
        string m_strPath;
        Rectangle m_rTileImage;
        Rectangle m_rSourceRect;
        Tile[,] m_pTileArr;

        SGP.ManagedDirect3D m_pD3D;
        SGP.ManagedTextureManager m_pTM;

        public Form1()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.ResizeRedraw, true);

            //Set the file path

            //////Ease of use for Will's testing////////
            //this.m_strPath = "C:\\Users\\Will\\Documents\\SGP\\Fusion\\fusion-spg-1208\\Fusion\\Fusion\\Resource\\Images";

            //////Actual////////
            MessageBox.Show("Please select your image folder");
            while (true)
            {
                FolderBrowserDialog open = new FolderBrowserDialog();
                if (open.ShowDialog() == DialogResult.OK)
                {
                    this.m_strPath = open.SelectedPath;
                    break;
                }
                MessageBox.Show("A folder must be selected");
            }

            this.m_rSourceRect = new Rectangle(0, 0, this.m_nTileWidth, this.m_nTileHeight);

            //Setup the initial tiles
            this.m_pTileArr = new Tile[this.m_nMapWidth, this.m_nMapHeight];
            for (int x = 0; x < this.m_nMapWidth; ++x)
            {
                for (int y = 0; y < this.m_nMapHeight; ++y)
                {
                    this.m_pTileArr[x, y].BCollidable = false;
                    this.m_pTileArr[x, y].SourceRect = this.m_rSourceRect;
                    this.m_pTileArr[x, y].StrTrigger = "";
                }
            }

            this.m_pD3D = SGP.ManagedDirect3D.Instance;
            this.m_pD3D.InitManagedDirect3D(this.graphicsPanelMap);
            this.m_pD3D.InitManagedDirect3D(this.graphicsPanelTiles);

            this.m_pTM = SGP.ManagedTextureManager.Instance;
            this.m_pTM.InitManagedTextureManager(SGP.ManagedDirect3D.Instance.Device, SGP.ManagedDirect3D.Instance.Sprite);

            //Set the image name
            MessageBox.Show("Thank you. Now please select your tile set");
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.InitialDirectory = this.m_strPath;
            dlg.RestoreDirectory = false;
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                this.m_strImageName = dlg.SafeFileName;
                this.m_nImgID = this.m_pTM.LoadTexture(this.m_strPath + '/' + this.m_strImageName, 0);

                int nWidth = this.m_pTM.GetTextureWidth(this.m_nImgID);
                int nHeight = this.m_pTM.GetTextureHeight(this.m_nImgID);
                this.m_rTileImage = new Rectangle(0, 0, nWidth, nHeight);
            }

            //setting up scrolling
            this.splitContainer2.Panel1.AutoScrollMinSize =
                new Size(this.m_nTileSetWidth * this.m_nTileWidth, this.m_nTileSetHeight * this.m_nTileHeight);
            this.splitContainer1.Panel2.AutoScrollMinSize =
                new Size(this.m_nMapWidth * this.m_nTileWidth, this.m_nMapHeight * this.m_nTileHeight);

            this.comboBoxTileHeight.SelectedIndex = 3;
            this.comboBoxTileWidth.SelectedIndex = 3;
        }

        public void Update()
        {
            
        }

        public void Render()
        {
            this.RenderMap();

            this.RenderTileSet();
        }

        private void RenderMap()
        {
            ////////////////////////////////////
            //Render to the Map Graphics Panel//
            ////////////////////////////////////
            this.m_pD3D.ChangeDisplayParam(this.graphicsPanelMap, true);

            this.m_pD3D.DeviceBegin();

            this.m_pD3D.Clear(Color.Black);

            //Draw tiles
            
            this.m_pD3D.SpriteBegin();

            for (int x = 0; x < this.m_nMapWidth; ++x)
            {
                for (int y = 0; y < this.m_nMapHeight; ++y)
                {
                    if (this.checkBoxTileImages.Checked && this.m_nImgID != -1)
                    {
                        this.m_pTM.Draw(this.m_nImgID, x * this.m_nTileWidth, y * this.m_nTileHeight, 1.0f, 1.0f,
                            this.m_pTileArr[x, y].SourceRect, 0, 0, 0.0f, Color.White);
                    }
                    if (this.checkBoxEvents.Checked)
                    {
                        string temp = this.m_pTileArr[x, y].StrTrigger;
                        this.m_pD3D.DrawText(temp,
                            x * this.m_nTileWidth,
                            y * this.m_nTileHeight,
                            Color.Red);
                    }
                }
            }
            this.m_pD3D.SpriteEnd();

            //Draw grid
            if (this.checkBoxGridLines.Checked)
            {
                for (int x = 0; x <= this.m_nMapWidth; ++x)
                {
                    this.m_pD3D.DrawLine(x * this.m_nTileWidth, 0, x * this.m_nTileWidth,
                        this.m_nMapHeight * this.m_nTileHeight, Color.Black, 1.0f);
                }
                for (int x = 0; x <= this.m_nMapHeight; ++x)
                {
                    this.m_pD3D.DrawLine(0, x * this.m_nTileHeight,
                        this.m_nMapWidth * this.m_nTileWidth, x * this.m_nTileHeight, Color.Black, 1.0f);
                }
            }

            //Draw collision rects
            if (this.checkBoxCollisionRects.Checked)
            {
                for (int x = 0; x < this.m_nMapWidth; ++x)
                {
                    for (int y = 0; y < this.m_nMapHeight; ++y)
                    {
                        if (this.m_pTileArr[x, y].BCollidable)
                        {
                            this.m_pD3D.DrawEmptyRect(
                                new Rectangle(x * this.m_nTileWidth,
                                    y * this.m_nTileHeight,
                                    this.m_nTileWidth,
                                    this.m_nTileHeight),
                                    Color.Red);
                        }
                    }
                }
            }

            this.m_pD3D.DeviceEnd();
            this.m_pD3D.Present();
        }

        private void RenderTileSet()
        {
            /////////////////////////////////////
            //Render to the tiles graphic panel//
            /////////////////////////////////////
            this.m_pD3D.ChangeDisplayParam(this.graphicsPanelTiles, true);

            this.m_pD3D.DeviceBegin();

            this.m_pD3D.Clear(Color.White);

            this.m_pD3D.SpriteBegin();
            if (this.m_nImgID != -1)
                this.m_pTM.Draw(this.m_nImgID, 0, 0, 1.0f, 1.0f, this.m_rTileImage, 0, 0, 0.0f, Color.White);
            this.m_pD3D.SpriteEnd();

            if (this.checkBoxGridLines.Checked)
            {
                for (int x = 0; x <= this.m_nTileSetWidth; ++x)
                {
                    this.m_pD3D.DrawLine(x * this.m_nTileWidth, 0, x * this.m_nTileWidth,
                        this.m_nTileSetHeight * this.m_nTileHeight, Color.Black, 1.0f);
                }
                for (int x = 0; x <= this.m_nTileSetHeight; ++x)
                {
                    this.m_pD3D.DrawLine(0, x * this.m_nTileHeight,
                        this.m_nTileSetWidth * this.m_nTileWidth, x * this.m_nTileHeight, Color.Black, 1.0f);
                }
            }

            this.m_pD3D.DrawEmptyRect(this.m_rSourceRect, Color.Red, 2.0f);

            this.m_pD3D.DeviceEnd();
            this.m_pD3D.Present();
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            this.Looping = false;
        }

        private void comboBoxTileWidth_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (this.comboBoxTileWidth.SelectedIndex)
            {
            case 0:
                {
                    this.m_nTileWidth = 8;
                    break;
                }
            case 1:
                {
                    this.m_nTileWidth = 16;
                    break;
                }
            case 2:
                {
                    this.m_nTileWidth = 32;
                    break;
                }
            case 3:
                {
                    this.m_nTileWidth = 64;
                    break;
                }
            default:
                {
                    this.m_nTileWidth = 64;
                    break;
                }
            }

            //Adjust scroll bars
            this.splitContainer1.Panel2.AutoScrollMinSize =
                new Size(this.m_nMapWidth * this.m_nTileWidth, this.m_nMapHeight * this.m_nTileHeight);
            //Reset red rect
            this.m_rSourceRect = new Rectangle(0, 0, this.m_nTileWidth, this.m_nTileHeight);

            //Adjust all tiles to the new source rect
            for (int x = 0; x < this.m_nMapWidth; ++x)
            {
                for (int y = 0; y < this.m_nMapHeight; ++y)
                {
                    this.m_pTileArr[x, y].SourceRect = this.m_rSourceRect;
                }
            }
        }

        private void comboBoxTileHeight_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (this.comboBoxTileHeight.SelectedIndex)
            {
                case 0:
                    {
                        this.m_nTileHeight = 8;
                        break;
                    }
                case 1:
                    {
                        this.m_nTileHeight = 16;
                        break;
                    }
                case 2:
                    {
                        this.m_nTileHeight = 32;
                        break;
                    }
                case 3:
                    {
                        this.m_nTileHeight = 64;
                        break;
                    }
                default:
                    {
                        this.m_nTileHeight = 64;
                        break;
                    }
            }

            //Adjust scroll bars
            this.splitContainer1.Panel2.AutoScrollMinSize =
                new Size(this.m_nMapWidth * this.m_nTileWidth, this.m_nMapHeight * this.m_nTileHeight);
            //Reset red rect
            this.m_rSourceRect = new Rectangle(0, 0, this.m_nTileWidth, this.m_nTileHeight);

            //Adjust all tiles to the new source rect
            for (int x = 0; x < this.m_nMapWidth; ++x)
            {
                for (int y = 0; y < this.m_nMapHeight; ++y)
                {
                    this.m_pTileArr[x, y].SourceRect = this.m_rSourceRect;
                }
            }
        }

        private void numericUpDownTileSetWidth_ValueChanged(object sender, EventArgs e)
        {
            this.m_nTileSetWidth = (int)this.numericUpDownTileSetWidth.Value;

            //Adjust scroll bars
            this.splitContainer2.Panel1.AutoScrollMinSize =
                new Size(this.m_nTileSetWidth * this.m_nTileWidth, this.m_nTileSetHeight * this.m_nTileHeight);
            //Reset red rect
            this.m_rSourceRect = new Rectangle(0, 0, this.m_nTileWidth, this.m_nTileHeight);
        }

        private void numericUpDownTileSetHeight_ValueChanged(object sender, EventArgs e)
        {
            this.m_nTileSetHeight = (int)this.numericUpDownTileSetHeight.Value;

            //Adjust scroll bars
            this.splitContainer2.Panel1.AutoScrollMinSize =
                new Size(this.m_nTileSetWidth * this.m_nTileWidth, this.m_nTileSetHeight * this.m_nTileHeight);
            //Reset red rect
            this.m_rSourceRect = new Rectangle(0, 0, this.m_nTileWidth, this.m_nTileHeight);
        }

        private void numericUpDownMapColumns_ValueChanged(object sender, EventArgs e)
        {
            Tile[,] temp = new Tile[(int)this.numericUpDownMapColumns.Value, this.m_nMapHeight];

            //If columns were lost
            if ((int)this.numericUpDownMapColumns.Value - this.m_nMapWidth <= 0)
            {
                for (int x = 0; x < (int)this.numericUpDownMapColumns.Value; ++x)
                {
                    for (int y = 0; y < this.m_nMapHeight; ++y)
                    {
                        temp[x, y] = this.m_pTileArr[x, y];
                    }
                }
            }
            //Columns were added
            else
            {
                for (int x = 0; x < (int)this.numericUpDownMapColumns.Value; ++x)
                {
                    for (int y = 0; y < this.m_nMapHeight; ++y)
                    {
                        if (x < this.m_nMapWidth)
                        {
                            temp[x, y] = this.m_pTileArr[x, y];
                        }
                        else
                        {
                            temp[x, y].BCollidable = false;
                            temp[x, y].SourceRect = new Rectangle(0, 0, this.m_nTileWidth, this.m_nTileHeight);
                            temp[x, y].StrTrigger = "";
                        }
                    }
                }
            }

            this.m_pTileArr = temp;


            this.m_nMapWidth = (int)this.numericUpDownMapColumns.Value;

            //Adjust scroll bars
            this.splitContainer1.Panel2.AutoScrollMinSize =
                new Size(this.m_nMapWidth * this.m_nTileWidth, this.m_nMapHeight * this.m_nTileHeight);
        }

        private void numericUpDownMapRows_ValueChanged(object sender, EventArgs e)
        {
            Tile[,] temp = new Tile[this.m_nMapWidth, (int)this.numericUpDownMapRows.Value];

            //If rows were lost
            if ((int)this.numericUpDownMapRows.Value - this.m_nMapHeight <= 0)
            {
                for (int x = 0; x < this.m_nMapWidth; ++x)
                {
                    for (int y = 0; y < (int)this.numericUpDownMapRows.Value; ++y)
                    {
                        temp[x, y] = this.m_pTileArr[x, y];
                    }
                }
            }
            //rows were added
            else
            {
                for (int x = 0; x < this.m_nMapWidth; ++x)
                {
                    for (int y = 0; y < (int)this.numericUpDownMapRows.Value; ++y)
                    {
                        if (y < this.m_nMapHeight)
                        {
                            temp[x, y] = this.m_pTileArr[x, y];
                        }
                        else
                        {
                            temp[x, y].BCollidable = false;
                            temp[x, y].SourceRect = new Rectangle(0, 0, this.m_nTileWidth, this.m_nTileHeight);
                            temp[x, y].StrTrigger = "";
                        }
                    }
                }
            }

            this.m_pTileArr = temp;

            this.m_nMapHeight = (int)this.numericUpDownMapRows.Value;

            //Adjust scroll bars
            this.splitContainer1.Panel2.AutoScrollMinSize =
                new Size(this.m_nMapWidth * this.m_nTileWidth, this.m_nMapHeight * this.m_nTileHeight);
        }

        private void graphicsPanelTiles_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.X < this.m_nTileSetWidth * this.m_nTileWidth && e.Y < this.m_nTileSetHeight * this.m_nTileHeight)
            {
                Rectangle ChangedRect = new Rectangle(
                    e.X / this.m_nTileWidth * this.m_nTileWidth,
                    e.Y / this.m_nTileHeight * this.m_nTileHeight,
                    this.m_nTileWidth, this.m_nTileHeight);
                this.m_rSourceRect = ChangedRect;
                
            }
        }

        private void graphicsPanelMap_MouseDown(object sender, MouseEventArgs e)
        {
            this.m_bMouseIsDown = true;
            if (e.X < this.m_nMapWidth * this.m_nTileWidth && e.Y < this.m_nMapHeight * this.m_nTileHeight
                    && e.X >= 0 && e.Y >= 0)
            {
                if(this.radioButtonImageLayer.Checked && this.checkBoxTileImages.Checked)
                    this.m_pTileArr[e.X / this.m_nTileWidth, e.Y / this.m_nTileHeight].SourceRect = this.m_rSourceRect;
                else if (this.radioButtonLogicLayer.Checked)
                {
                    if (this.checkBoxCollisionRects.Checked)
                        this.m_pTileArr[e.X / this.m_nTileWidth, e.Y / this.m_nTileHeight].BCollidable
                            = this.checkBoxCollision.Checked;
                    if (this.checkBoxEvents.Checked)
                        this.m_pTileArr[e.X / this.m_nTileWidth, e.Y / this.m_nTileHeight].StrTrigger =
                            this.GetComboBoxEvent();
                }
            }
        }

        private void graphicsPanelMap_MouseLeave(object sender, EventArgs e)
        {
            this.m_bMouseIsDown = false;
        }

        private void graphicsPanelMap_MouseUp(object sender, MouseEventArgs e)
        {
            this.m_bMouseIsDown = false;
        }

        private void graphicsPanelMap_MouseMove(object sender, MouseEventArgs e)
        {
            if (this.m_bMouseIsDown)
            {
                if (e.X < this.m_nMapWidth * this.m_nTileWidth && e.Y < this.m_nMapHeight * this.m_nTileHeight
                    && e.X >= 0 && e.Y >= 0)
                {
                    if(this.radioButtonImageLayer.Checked)
                        this.m_pTileArr[e.X / this.m_nTileWidth, e.Y / this.m_nTileHeight].SourceRect
                            = this.m_rSourceRect;
                    else if (this.radioButtonLogicLayer.Checked)
                    {
                        if (this.checkBoxLogic.Checked)
                        {
                            this.m_pTileArr[e.X / this.m_nTileWidth, e.Y / this.m_nTileHeight].BCollidable
                                = this.checkBoxCollision.Checked;
                            this.m_pTileArr[e.X / this.m_nTileWidth, e.Y / this.m_nTileHeight].StrTrigger =
                                this.GetComboBoxEvent();
                        }
                    }
                }
            }
        }

        private string GetComboBoxEvent()
        {
            switch (this.comboBoxEvents.SelectedIndex)
            {
                case 0:
                    return "";
                case 1:
                    return "Go Red";
                case 2:
                    return "Spawn Enemy";
                case 3:
                    return "Win";
                default:
                    return "";
            }
        }

        private void graphicsPanelMap_Paint(object sender, PaintEventArgs e)
        {
            this.RenderMap();
        }

        private void graphicsPanelTiles_Paint(object sender, PaintEventArgs e)
        {
            this.RenderTileSet();
        }

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //reset all variables to a default
            this.numericUpDownMapColumns.Value = 25;
            this.numericUpDownMapRows.Value = 20;
            this.numericUpDownTileSetHeight.Value = 2;
            this.numericUpDownTileSetWidth.Value = 4;
            this.checkBoxGridLines.Checked = true;
            this.comboBoxTileHeight.SelectedIndex = 3;
            this.comboBoxTileWidth.SelectedIndex = 3;

            this.m_bMouseIsDown = false;
            this.m_rSourceRect = new Rectangle(0, 0, this.m_nTileWidth, this.m_nTileHeight);
            

            //Set the file path
            //////Ease of use for faster testing////////
            //this.m_strPath = "C:\\Users\\Will\\Documents\\SGP\\Fusion\\fusion-spg-1208\\Fusion\\Fusion\\Resource\\Images";
            //////Actual////////
            MessageBox.Show("Please select your image folder");
            while (true)
            {
                FolderBrowserDialog open = new FolderBrowserDialog();
                if (open.ShowDialog() == DialogResult.OK)
                {
                    this.m_strPath = open.SelectedPath;
                    break;
                }
                MessageBox.Show("A folder must be selected");
            }

            //Set the image name
            MessageBox.Show("Select your tile set");
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.InitialDirectory = this.m_strPath;
            dlg.RestoreDirectory = true;
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                this.m_strImageName = dlg.SafeFileName;

                if (this.m_nImgID != -1)
                    this.m_pTM.ReleaseTexture(this.m_nImgID);
                this.m_nImgID = this.m_pTM.LoadTexture(this.m_strPath + '/' + this.m_strImageName, 0);

                int nWidth = this.m_pTM.GetTextureWidth(this.m_nImgID);
                int nHeight = this.m_pTM.GetTextureHeight(this.m_nImgID);
                this.m_rTileImage = new Rectangle(0, 0, nWidth, nHeight);
            }

            //Setup the initial tiles
            this.m_pTileArr = new Tile[this.m_nMapWidth, this.m_nMapHeight];
            for (int x = 0; x < this.m_nMapWidth; ++x)
            {
                for (int y = 0; y < this.m_nMapHeight; ++y)
                {
                    this.m_pTileArr[x, y].BCollidable = false;
                    this.m_pTileArr[x, y].SourceRect = this.m_rSourceRect;
                    this.m_pTileArr[x, y].StrTrigger = "";
                }
            }

            //setting up scrolling
            this.splitContainer2.Panel1.AutoScrollMinSize =
                new Size(this.m_nTileSetWidth * this.m_nTileWidth, this.m_nTileSetHeight * this.m_nTileHeight);
            this.splitContainer1.Panel2.AutoScrollMinSize =
                new Size(this.m_nMapWidth * this.m_nTileWidth, this.m_nMapHeight * this.m_nTileHeight);
        }

        private void importTileSetToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.InitialDirectory = this.m_strPath;
            dlg.RestoreDirectory = true;
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                this.m_strImageName = dlg.SafeFileName;
                if (this.m_nImgID != -1)
                    this.m_pTM.ReleaseTexture(this.m_nImgID);
                this.m_nImgID = this.m_pTM.LoadTexture(this.m_strPath + '/' + this.m_strImageName, 0);

                int nWidth = this.m_pTM.GetTextureWidth(this.m_nImgID);
                int nHeight = this.m_pTM.GetTextureHeight(this.m_nImgID);
                this.m_rTileImage = new Rectangle(0, 0, nWidth, nHeight);
            }
        }

        private void radioButtonImageLayer_CheckedChanged(object sender, EventArgs e)
        {
            this.m_bImageLayer = !this.m_bImageLayer;
            this.graphicsPanelTiles.Enabled = !this.graphicsPanelTiles.Enabled;
            this.groupBoxLogicTiles.Enabled = !this.groupBoxLogicTiles.Enabled;
        }

        private void checkBoxLogic_CheckedChanged(object sender, EventArgs e)
        {
            this.checkBoxCollisionRects.Checked =
                this.checkBoxEvents.Checked =
                this.checkBoxLogic.Checked;
        }

        private void checkBoxCollision_CheckedChanged(object sender, EventArgs e)
        {
            if (this.checkBoxCollision.Checked)
            {
                this.comboBoxEvents.Enabled = true;
                this.labelEvent.Enabled = true;
            }
            else
            {
                this.comboBoxEvents.SelectedIndex = 0;
                this.comboBoxEvents.Enabled = false;
                this.labelEvent.Enabled = false;
            }
        }

        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Windows.Forms.SaveFileDialog dlg = new SaveFileDialog();
            dlg.Filter = "All Files|*.*|Xml Files|*.xml";
            dlg.FilterIndex = 2;
            dlg.DefaultExt = "xml";
            dlg.Title = "Save File As";

            dlg.AddExtension = true;

            if (dlg.ShowDialog() == DialogResult.OK)
            {
                SaveFile(dlg.FileName);
            }
        }

        private void SaveFile(string _filename)
        {
            XElement xRoot = new XElement("layer");

            XElement xLayer_info = new XElement("layer_info");
            xRoot.Add(xLayer_info);

            XAttribute xMapHeight = new XAttribute("Height", this.m_nMapHeight);
            xLayer_info.Add(xMapHeight);

            XAttribute xMapWidth = new XAttribute("Width", this.m_nMapWidth);
            xLayer_info.Add(xMapWidth);

            XElement xImage = new XElement("image_name");
            xImage.Value = this.m_strImageName;
            xLayer_info.Add(xImage);

            for (int y = 0; y < this.m_nMapHeight; ++y)
            {
                for (int x = 0; x < this.m_nMapWidth; ++x)
                {
                    XElement xTile_info = new XElement("tile_info");
                    

                    XAttribute Collidable = new XAttribute("Collidable", (this.m_pTileArr[x, y].BCollidable ? 1 : 0));
                    xTile_info.Add(Collidable);

                    XAttribute HasEvent = new XAttribute("HasEvent", (this.m_pTileArr[x, y].StrTrigger == "" ? 0 : 1));
                    xTile_info.Add(HasEvent);

                    XAttribute Height = new XAttribute("Height", this.m_nTileHeight);
                    xTile_info.Add(Height);

                    XAttribute SourceRect_Left = new XAttribute("SourceRect_Left", this.m_pTileArr[x, y].SourceRect.Left);
                    xTile_info.Add(SourceRect_Left);

                    XAttribute SourceRect_Top = new XAttribute("SourceRect_Top", this.m_pTileArr[x, y].SourceRect.Top);
                    xTile_info.Add(SourceRect_Top);

                    XAttribute SourceRect_Right = new XAttribute("SourceRect_Right", this.m_pTileArr[x, y].SourceRect.Right);
                    xTile_info.Add(SourceRect_Right);

                    XAttribute SourceRect_Bottom = new XAttribute("SourceRect_Bottom", this.m_pTileArr[x, y].SourceRect.Bottom);
                    xTile_info.Add(SourceRect_Bottom);

                    XAttribute Trigger = new XAttribute("Trigger", this.m_pTileArr[x, y].StrTrigger);
                    xTile_info.Add(Trigger);

                    XAttribute Width = new XAttribute("Width", this.m_nTileWidth);
                    xTile_info.Add(Width);

                    XAttribute X = new XAttribute("X", x * this.m_nTileWidth);
                    xTile_info.Add(X);

                    XAttribute Y = new XAttribute("Y", y * this.m_nTileHeight);
                    xTile_info.Add(Y);


                    xRoot.Add(xTile_info);
                }
            }
            xRoot.Save(_filename);
        }

        private void OpenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "All Files|*.*|Xml Files|*.xml";
            dlg.FilterIndex = 2;

            if (DialogResult.OK == dlg.ShowDialog())
            {
                XElement Root = XElement.Load(dlg.FileName);

                //Load layer info
                XElement Layer = Root.Element("layer_info");

                this.numericUpDownMapRows.Value = int.Parse(Layer.Attribute("Height").Value);

                this.numericUpDownMapColumns.Value = int.Parse(Layer.Attribute("Width").Value);

                this.m_strImageName = Layer.Element("image_name").Value.ToString();

                //Reset variables
                if (this.m_nImgID != -1)
                    this.m_pTM.ReleaseTexture(this.m_nImgID);
                this.m_nImgID = this.m_pTM.LoadTexture(this.m_strPath + '/' + this.m_strImageName, 0);

                int nWidth = this.m_pTM.GetTextureWidth(this.m_nImgID);
                int nHeight = this.m_pTM.GetTextureHeight(this.m_nImgID);
                this.m_rTileImage = new Rectangle(0, 0, nWidth, nHeight);

                //Load each tile
                int x = 0, y = 0;
                IEnumerable<XElement> tile = Root.Elements("tile_info");
                foreach (XElement xTile in tile)
                {
                    if (x == 0 && y == 0)
                    {
                        //Set tile height
                        switch (int.Parse(xTile.Attribute("Height").Value))
                        {
                            case 8:
                                this.comboBoxTileHeight.SelectedIndex = 0;
                                break;
                            case 16:
                                this.comboBoxTileHeight.SelectedIndex = 1;
                                break;
                            case 32:
                                this.comboBoxTileHeight.SelectedIndex = 2;
                                break;
                            case 64:
                                this.comboBoxTileHeight.SelectedIndex = 3;
                                break;
                            default:
                                this.comboBoxTileHeight.SelectedIndex = 3;
                                break;
                        }
                        //set tile width
                        switch (int.Parse(xTile.Attribute("Width").Value))
                        {
                            case 8:
                                this.comboBoxTileWidth.SelectedIndex = 0;
                                break;
                            case 16:
                                this.comboBoxTileWidth.SelectedIndex = 1;
                                break;
                            case 32:
                                this.comboBoxTileWidth.SelectedIndex = 2;
                                break;
                            case 64:
                                this.comboBoxTileWidth.SelectedIndex = 3;
                                break;
                            default:
                                this.comboBoxTileWidth.SelectedIndex = 3;
                                break;
                        }
                    }
                    this.m_pTileArr[x, y].BCollidable = (xTile.Attribute("Collidable").Value == "1" ? true : false);
                    this.m_pTileArr[x, y].SourceRect = new Rectangle(
                        int.Parse(xTile.Attribute("SourceRect_Left").Value),
                        int.Parse(xTile.Attribute("SourceRect_Top").Value),
                        int.Parse(xTile.Attribute("SourceRect_Right").Value),
                        int.Parse(xTile.Attribute("SourceRect_Bottom").Value));
                    this.m_pTileArr[x, y].StrTrigger = xTile.Attribute("Trigger").Value;

                    ++x;
                    if (x >= this.m_nMapWidth)
                    {
                        x -= this.m_nMapWidth;
                        ++y;
                    }
                    if (y >= this.m_nMapHeight)
                        y -= this.m_nMapHeight;
                }
            }
        }
    }
}
